package com.bob.web.service.system;

import com.bob.web.common.constant.CodeConstant;
import com.bob.web.common.constant.Page;
import com.bob.web.common.exception.ServiceException;
import com.bob.web.dao.AdminDao;
import com.bob.web.dao.ResourceDao;
import com.bob.web.dao.RoleDao;
import com.bob.web.entity.system.Admin;
import com.bob.web.entity.system.Resource;
import com.bob.web.entity.system.Role;
import com.bob.web.service.BaseService;
import com.bob.web.util.CollectionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.management.Query;
import java.util.*;

/**
 * 名称: BaseService<br>
 * 描述:<br>
 * 类型: JAVA<br>
 * 最近修改时间:2017/7/21 15:52<br>
 *
 * @author BoYangsh
 * @version [版本号, V1.0]
 * @since 2017/7/21 15:52
 */
//@Service
public class SystemService extends BaseService{

	@Autowired
	private ResourceDao resourceDao;
	@Autowired
	private AdminDao adminDao;
	@Autowired
	private RoleDao roleDao;

	/**
	 * 查找资源分页数据
	 * @param page
	 */
	public void findResourcePage(Page<Resource> page) {
		resourceDao.findPage(page);
		page.getResult().forEach(resource -> {
			if(resource.getAdminId() != null) {
				resource.setAdminName(adminDao.findUserById(resource.getAdminId()).getUsername());
			}
		});
	}

	/**
	 * 添加资源
	 * @param resource
     */
	public void addResource(Resource resource) {
		resource.setCreateTime(new Date());
		resource.setAdminId(getCurrentUser().getId());
		resourceDao.add(resource);
	}

	/**
	 * 查找一级菜单
	 * @return
	 */
	public List<Resource> findFirstLevelResource() {
		List<Resource> resources = resourceDao.findResourcesByMenuLevel(Resource.MENU_LEVEL_FIRST);
		return resources;
	}

	/**
	 * 查找二级菜单
	 * @return
	 */
	public List<Resource> findSecondLevelResource() {
		List<Resource> resources = resourceDao.findResourcesByMenuLevel(Resource.MENU_LEVEL_SECONDE);
		return resources;
	}

	/**
	 * 删除资源
	 * @param id
	 */
	public void removeResource(String id) {
		resourceDao.remove(id);
	}

	/**
	 * 查找角色的分页数据
	 * @param page
     */
	public void findRolePage(Page<Role> page) {
		roleDao	.findPage(page);
		page.getResult().forEach(role -> {
			role.setAdminName(adminDao.findUserById(role.getAdminId()).getUsername());
		});
	}

	/**
	 * 添加角色
	 * @param role
     */
	public void addRole(Role role) {
		role.setAdminId(getCurrentUser().getId());
		role.setCreateTime(new Date());
		roleDao.addRole(role);
	}

	/**
	 * 获得资源树
	 * @return
     */
	public List<Resource> findResourceTree(Long roleId) {
		Role role = roleDao.findRoleById(roleId, "resources");
		List<Long> resourceIds = role.getResources() == null ? new ArrayList<>() : role.getResources();
		List<Resource> resources = resourceDao.findAllResources();
		List<Resource> resourceTree = new ArrayList<>();
		Map<Long, Resource> firstMenuMap = new HashMap<>();
		Map<Long, Resource> secondMenuMap = new HashMap<>();
		List<Resource> buttonResources = new ArrayList<>();
		//首先取出所有的菜单，系统中只有两级菜单
		for(Resource resource : resources) {
			//判断是否被选中
			if(resourceIds.contains(resource.getId())) {
				resource.setChecked(true);
			}
			if(Resource.MENU_LEVEL_FIRST.equals(resource.getMenuLevel())) {
				firstMenuMap.put(resource.getId(), resource);
			}else if(Resource.MENU_LEVEL_SECONDE.equals(resource.getMenuLevel())) {
				secondMenuMap.put(resource.getId(), resource);
			}else {
				if(Resource.TYPE_BUTTON.equals(resource.getType()));
				buttonResources.add(resource);
			}
		}
		//再找出二级菜单下面绑定的按钮
		for(Resource resource : buttonResources) {
				Long pid = resource.getPId();
				if(CollectionUtil.isEmpty(secondMenuMap.get(pid).getChildResources())) {
					List<Resource> childResources = new ArrayList<>();
					childResources.add(resource);
				}else {
					secondMenuMap.get(pid).getChildResources().add(resource);
				}
		}
		//再把二级菜单绑定到一级菜单上
		for(Long id : secondMenuMap.keySet()) {
			Resource resource = secondMenuMap.get(id);
			Resource firstMenuResource = firstMenuMap.get(resource.getPId());
			if(firstMenuResource != null) {
				if(CollectionUtil.isEmpty(firstMenuResource.getChildResources())) {
					List<Resource> childResource = new ArrayList<>();
					childResource.add(resource);
					firstMenuResource.setChildResources(childResource);
				}else {
					firstMenuResource.getChildResources().add(resource);
				}
			}
		}
		//将map转变成list
		firstMenuMap.forEach((id, resource) -> {
			resourceTree.add(resource);
		});
		return resourceTree;
	}

	/**
	 * 为角色分配资源
	 * @param role
	 */
	public void allocateResourceForRole(Role role) {
		//校验必要参数
		if(role == null || role.getId() == null || CollectionUtil.isEmpty(role.getResources())) {
			throw new ServiceException(CodeConstant.PARAMS_ERROR);
		}
		//确保子资源选中之后，父资源也必须要包含在其中
		List<Resource> resources = resourceDao.findAllResources("_id", "pId");
		Map<Long, Resource> resourceMap = CollectionUtil.buildMap(resources, Long.class, Resource.class, "id");
		Set<Long> resourceIds = new HashSet<>();
		resourceIds.addAll(role.getResources());
		if(!CollectionUtil.isEmpty(resourceIds)) {
			Iterator<Long> iterator = resourceIds.iterator();
			while(iterator.hasNext()) {
				Long id = iterator.next();
				checkResourceHavePIdOrNot(resourceMap, id, resourceIds);
			}
		}
		roleDao.findAndModifyById(role.getId(), resourceIds);
	}

	/**
	 * 判断是否有父类资源，如果有则把父类资源的id也加入进来
	 * @param resourceMap
	 * @param resourceId
	 * @param resourceIds
	 */
	private void checkResourceHavePIdOrNot(Map<Long, Resource> resourceMap, Long resourceId, Set<Long> resourceIds) {
		Resource resource = resourceMap.get(resourceId);
		if(resource.getPId() != null) {
			resourceIds.add(resource.getPId());
			checkResourceHavePIdOrNot(resourceMap, resource.getPId(), resourceIds);
		}
	}

	/**
	 * 查找所有的角色
	 * @return
	 */
	public List<Role> findAllRoles() {
		return roleDao.findAllRoles();
	}

	/**
	 * 根据管理员id查找所有的角色
	 * @param adminId
	 * @return
	 */
	public List<Role> findAllRolesByAdminId(Long adminId) {
		List<Role> roles = roleDao.findAllRoles();
		//处理管理员拥有的角色
		Admin admin = adminDao.findUserById(adminId);
		if(!CollectionUtil.isEmpty(roles)) {
			roles.forEach(role -> {
				if(admin.getRoleIds() != null && admin.getRoleIds().contains(role.getId())) {
					role.setOwned(true);
				}
			});
		}
		return roles;
	}
}
